home *** CD-ROM | disk | FTP | other *** search
- {******************************************************************}
- { }
- { Mancala }
- { Turbo Pascal for Windows }
- { Copyright (c) 1991 by Swan Software. All rights reserved. }
- { }
- {******************************************************************}
-
- { uwindow.pas -- Main window object for Mancala }
-
- unit UWindow;
-
- interface
-
- uses WinTypes, WinProcs, WObjects, Strings,
- UGlobals, UGraphics, UPlay, UMove, UOptions, Idents;
-
- type
-
- PMancalaWin = ^TMancalaWin;
- TMancalaWin = object(TWindow)
- BkPattern: HBrush; { Window background--forced to white }
- Help: Boolean; { True to display help in WMCommand }
- HelpFileName: PChar; { Online help file name }
- constructor Init(AParent: PWindowsObject; ATitle: PChar);
- destructor Done; virtual;
- procedure SetupWindow; virtual;
- procedure GetWindowClass(var AWndClass: TWndClass); virtual;
- function GetClassName: PChar; virtual;
- procedure Paint(PaintDC: HDC; var PaintInfo: TPaintStruct); virtual;
- function CanClose: Boolean; virtual;
- procedure MakeMoves;
- procedure CMGameNew(var Msg: TMessage);
- virtual cm_First + cm_GameNew;
- procedure CMGameExit(var Msg: TMessage);
- virtual cm_First + cm_GameExit;
- procedure CMEditOptions(var Msg: TMessage);
- virtual cm_First + cm_EditOptions;
- procedure CMActionReplay(var Msg: TMessage);
- virtual cm_First + cm_ActionReplay;
- procedure CMActionPass(var Msg: TMessage);
- virtual cm_First + cm_ActionPass;
- procedure CMActionSwitch(var Msg: TMessage);
- virtual cm_First + cm_ActionSwitch;
- procedure CMHelpIndex(var Msg: TMessage);
- virtual cm_First + cm_HelpIndex;
- procedure CMHelpUsing(var Msg: TMessage);
- virtual cm_First + cm_HelpUsing;
- procedure CMHelpAbout(var Msg: TMessage);
- virtual cm_First + cm_HelpAbout;
- procedure WMLButtonDown(var Msg: TMessage);
- virtual wm_First + wm_LButtonDown;
- procedure WMCommand(var Msg: TMessage);
- virtual wm_First + wm_Command;
- procedure WMSize(var Msg: TMessage);
- virtual wm_First + wm_Size;
- procedure WMEnterIdle(var Msg: TMessage);
- virtual wm_First + wm_EnterIdle;
- procedure WMDestroy(var Msg: TMessage);
- virtual wm_First + wm_Destroy;
- end;
-
-
- implementation
-
-
- {- Toggle a checkmarked menu item on or off }
-
- procedure ToggleCheck(Menu: HMenu; MenuItemID: Word);
- var
- MAttr, WCheck: Word;
- begin
- MAttr := GetMenuState(Menu, MenuItemID, mf_ByCommand);
- if (MAttr and mf_Checked) = mf_Checked then
- WCheck := mf_ByCommand or mf_Unchecked
- else
- WCheck := mf_ByCommand or mf_Checked;
- CheckMenuItem(Menu, MenuItemID, WCheck);
- end;
-
-
- {- Construct Mancala window object }
-
- constructor TMancalaWin.Init(AParent: PWindowsObject; ATitle: PChar);
- const
- ExeNameMaxSize = 128;
- var
- FileNameLen: Integer;
- FileName: array[0 .. ExeNameMaxSize + 1] of Char;
- I: Integer;
- begin
- TWindow.Init(AParent, ATitle);
- with Attr do
- begin
- X := XCenter - XMax div 2;
- Y := YCenter - YMax div 2;
- W := XMax;
- H := YMax;
- Style := ws_Caption + ws_SysMenu + ws_MinimizeBox + ws_MaximizeBox;
- Menu := LoadMenu(HInstance, PChar(id_Menu));
- ToggleCheck(Menu, (cm_EditLevel1 + MaxPly) - 1);
- end;
- BkPattern := CreateSolidBrush(CBackground);
- InitUGraphics;
- {- Construct HelpFileName from Module Name }
- FileNameLen := GetModuleFileName(HInstance, FileName, ExeNameMaxSize);
- I := FileNameLen - 1;
- while (I <> 0) and ((FileName[I] <> '\') and (FileName[I] <> ':')) do
- Dec(I);
- Inc(I);
- if I + 13 <= ExeNameMaxSize then
- StrCopy(@FileName[I], 'mancala.hlp')
- else
- StrCopy(@FileName[I], '?');
- HelpFileName := StrNew(FileName);
- Help := false;
- end;
-
-
- {- Destroy TMancalaWin window and the custom background pattern }
-
- destructor TMancalaWin.Done;
- begin
- DeleteObject(BkPattern);
- DeleteObject(FlashBits);
- StrDispose(HelpFileName);
- TWindow.Done;
- end;
-
-
- {- Perform initializations for which window handle is needed }
-
- procedure TMancalaWin.SetupWindow;
- begin
- TWindow.SetupWindow;
- NewGame(Side);
- end;
-
-
- {- Return name for new window class }
-
- function TMancalaWin.GetClassName: PChar;
- begin
- GetClassName := 'MancalaWin';
- end;
-
-
- {- Modify window class to use custom icon }
-
- procedure TMancalaWin.GetWindowClass(var AWndClass: TWndClass);
- begin
- TWindow.GetWindowClass(AWndClass);
- AWndClass.HIcon := LoadIcon(HInstance, PChar(id_Icon));
- AWndClass.HBrBackground := BkPattern;
- end;
-
-
- {- Display program's icon in window }
-
- procedure TMancalaWin.Paint(PaintDC: HDC; var PaintInfo: TPaintStruct);
- begin
- DrawGameboard(PaintDC, MainPosition.Gameboard);
- end;
-
-
- {- Return true if it's okay to close window (i.e. to end the program) }
-
- function TMancalaWin.CanClose: Boolean;
- begin
- CanClose := MessageBox(HWindow, 'End Mancala now?', 'Please answer',
- mb_YesNo or mb_IconQuestion) = id_Yes
- end;
-
-
- {- Make human and computer moves. }
-
- procedure TMancalaWin.MakeMoves;
- var
- NextMove: OneMove; { Result from GetMove }
- Score: Integer; { Unused, returned by MakeMove }
- DC: HDC; { Display context for visuals }
- begin
- DC := GetDC(HWindow);
- if not MainPosition.Win then
- if GetMove(Side, NextMove) then
- begin
- PrepareReplay(NextMove);
- EnableMenuItem(Attr.Menu, cm_ActionReplay, mf_Enabled or mf_ByCommand);
- MakeGraphMove(DC, MainPosition, Side, NextMove); { Visual }
- MakeMove(MainPosition, Side, NextMove, Score); { Logical }
- with MainPosition do
- begin
- if Win then
- begin
- EnableMenuItem(Attr.Menu, cm_ActionPass, mf_Grayed or mf_ByCommand);
- EnableMenuItem(Attr.Menu, cm_ActionSwitch, mf_Grayed or mf_ByCommand);
- if WinningSide = computer then
- DisplayMessage(DC, I_win)
- else
- DisplayMessage(DC, You_win);
- end else
- if not GoAgain then
- begin
- if Side = computer then
- begin
- Side := human;
- DisplayMessage(DC, Its_your_move);
- end else
- begin
- Side := computer;
- DisplayMessage(DC, Its_my_move);
- end
- end else
- begin
- if Side = computer then
- DisplayMessage(DC, I_go_again)
- else
- DisplayMessage(DC, You_go_again)
- end;
- end;
- end;
- ReleaseDC(HWindow, DC);
- end;
-
-
- {- Begin a new game }
-
- procedure TMancalaWin.CMGameNew(var Msg: TMessage);
- begin
- if MessageBox(HWindow, 'Start a new game?', 'Please answer',
- mb_YesNo or mb_IconQuestion) = id_Yes then
- begin
- NewGame(Side);
- EnableMenuitem(Attr.Menu, cm_ActionReplay, mf_Grayed or mf_ByCommand);
- EnableMenuItem(Attr.Menu, cm_ActionPass, mf_Enabled or mf_ByCommand);
- EnableMenuItem(Attr.Menu, cm_ActionSwitch, mf_Enabled or mf_ByCommand);
- end;
- end;
-
-
- {- Quit program }
-
- procedure TMancalaWin.CMGameExit(var Msg: TMessage);
- begin
- CloseWindow;
- end;
-
-
- {- Select program options }
-
- procedure TMancalaWin.CMEditOptions(var Msg: TMessage);
- var
- Dialog: OptDialog;
- Options: OptionsRec;
- S: String[2];
- N, ErrorCode: Integer;
- begin
- Str(PebblesPerCup, S);
- StrPCopy(Options.PPCLine, S);
- Dialog.Init(@Self, PChar(id_Options), @Options);
- if Dialog.Execute = id_Ok then
- begin
- Val(Options.PPCLine, N, ErrorCode);
- if ErrorCode = 0 then
- PebblesPerCup := N;
- if (PebblesPerCup < 1) or (PebblesPerCup > 9) then
- PebblesPerCup := 3
- end;
- Dialog.Done;
- end;
-
-
- {- Execute instant replay feature }
-
- procedure TMancalaWin.CMActionReplay(var Msg: TMessage);
- var
- Score: Integer; { Returned by MakeMove (ignored) }
- OldMessage: Integer; { Saved message number }
- DC: HDC;
- begin
- if ReplayOk then
- begin
- MainPosition := ReplayBoard;
- OldMessage := CurrentMessage;
- CurrentMessage := Instant_Replay;
- DC := GetDC(HWindow);
- DrawGameboard(DC, MainPosition.Gameboard);
- MakeGraphMove(DC, MainPosition, ReplaySide, ReplayMove);
- MakeMove(MainPosition, ReplaySide, ReplayMove, Score);
- DisplayMessage(DC, OldMessage);
- ReleaseDC(HWindow, DC);
- end;
- end;
-
-
- {- Pass turn (used to let computer go first or next }
-
- procedure TMancalaWin.CMActionPass(var Msg: TMessage);
- var
- DC: HDC;
- begin
- if MessageBox(HWindow, 'Let computer move next?', 'Please answer',
- mb_YesNo or mb_IconQuestion) = id_Yes then
- begin
- Side := Computer;
- DC := GetDC(HWindow);
- DisplayMessage(DC, Its_my_move);
- ReleaseDC(HWindow, DC);
- while (not MainPosition.Win) and (Side = computer) do
- MakeMoves;
- end;
- end;
-
-
- {- Play with the other side's pieces }
-
- procedure TMancalaWin.CMActionSwitch(var Msg: TMessage);
- var
- NewBoard: Board;
- CompCup, HumanCup: CupIndex;
- begin
- with MainPosition do
- begin
- NewBoard[HumanKalah] := Gameboard[CompKalah];
- NewBoard[CompKalah] := Gameboard[HumanKalah];
- CompCup := compFirstCup;
- for HumanCup := humanFirstCup to humanLastCup do
- begin
- NewBoard[HumanCup] := Gameboard[CompCup];
- NewBoard[CompCup] := Gameboard[HumanCup];
- Inc(CompCup);
- end;
- Gameboard := NewBoard;
- end;
- InvalidateRect(HWindow, nil, true);
- end;
-
-
- {- Display Windows Help index }
-
- procedure TMancalaWin.CMHelpIndex(var Msg: TMessage);
- begin
- WinHelp(HWindow, HelpFileName, Help_Index, 0);
- end;
-
-
- {- Display Windows Help on Help }
-
- procedure TMancalaWin.CMHelpUsing(var Msg: TMessage);
- begin
- WinHelp(HWindow, 'WINHELP.HLP', Help_Index, 0);
- end;
-
-
- {- Display About box dialog }
-
- procedure TMancalaWin.CMHelpAbout(var Msg: TMessage);
- var
- Dialog: TDialog;
- begin
- Dialog.Init(@Self, PChar(id_About));
- Dialog.Execute;
- Dialog.Done;
- end;
-
-
- {- Respond to left-button click. Make move if inside cup }
-
- procedure TMancalaWin.WMLButtonDown(var Msg: TMessage);
- var
- P: TPoint;
- R: TRect;
- CupNum: CupIndex;
- begin
- with Msg do
- begin
- P.X := LParamLo;
- P.Y := LParamHi;
- for CupNum := 0 to maxCupIndex do
- begin
- with CupCoords[CupNum] do
- SetRect(R, X, Y + 15, X + 52, Y + 52);
- if PtInRect(R, P) then
- if (HumanFirstCup <= CupNum) and (CupNum <= HumanLastCup) then
- HumanMove := CupNum
- end;
- end;
- if HumanMove >= 0 then
- begin
- MakeMoves; { Make human's move }
- while (not MainPosition.Win) and (Side = computer) do
- MakeMoves; { Make computer's response(s) }
- end;
- end;
-
-
- {- Intercept all wm_Command (Options:Leveln) command messages }
-
- procedure TMancalaWin.WMCommand(var Msg: TMessage);
- var
- CupNum: Integer;
- Location: LongInt;
- HelpContextId: LongInt;
-
- {- Local to WMCommand: Display help rather than execute a command }
- procedure DisplayHelp;
- begin
- case Msg.WParam of
- cm_GameNew: HelpContextId := hc_command_new;
- cm_GameExit: HelpContextId := hc_command_exit;
- cm_EditOptions: HelpContextId := hc_command_options;
- cm_EditLevel1 .. cm_EditLevel7: HelpContextId := hc_command_level;
- cm_ActionReplay: HelpContextId := hc_command_replay;
- cm_ActionPass: HelpContextId := hc_command_pass;
- cm_ActionSwitch: HelpContextId := hc_command_switch;
- cm_HelpIndex: HelpContextId := hc_command_index;
- cm_HelpUsing: HelpContextId := hc_command_using_help;
- cm_HelpAbout: HelpContextId := hc_command_about;
- else
- HelpContextId := 0;
- end;
- if HelpContextId <> 0 then
- WinHelp(HWindow, HelpFileName, Help_Context, HelpContextId)
- else begin
- MessageBox(HWindow, 'Help not available for item', 'Message', mb_Ok);
- DefWndProc(Msg);
- end;
- Help := false;
- end;
-
- begin
- if Help then DisplayHelp else
- begin
- case Msg.WParam of
- cm_EditLevel1 .. cm_EditLevel7:
- begin {- Select difficulty level (i.e. search "ply") }
- ToggleCheck(Attr.Menu, (cm_EditLevel1 + MaxPly) - 1);
- MaxPly := (Msg.WParam - cm_EditLevel1) + 1;
- ToggleCheck(Attr.Menu, (cm_EditLevel1 + MaxPly) - 1);
- end;
- cm_Move1 .. cm_Move6: { cm_Move7 .. cm_Move 9 ignored in this version }
- begin {- Simulate mouse click for keyboard control }
- CupNum := humanFirstCup + (Msg.WParam - cm_Move1);
- with CupCoords[CupNum] do
- Location := MAKELONG(X, Y + 20);
- PostMessage(HWindow, wm_LButtonDown, 0, Location);
- PostMessage(HWindow, wm_LButtonUp, 0, Location);
- end;
- else
- TWindow.WMCommand(Msg)
- end;
- end;
- end;
-
-
- {- Recalculate postions when window size changes }
-
- procedure TMancalaWin.WMSize(var Msg: TMessage);
- var
- R: TRect;
- begin
- GetClientRect(HWindow, R);
- XMax := R.Right;
- if XMax < 524 then XMax := 524;
- YMax := R.Bottom;
- if YMax < 360 + GetSystemMetrics(sm_CYMenu) then
- YMax := 360 + GetSystemMetrics(sm_CYMenu);
- XCenter := GetSystemMetrics(sm_CXScreen) div 2;
- YCenter := GetSystemMetrics(sm_CYScreen) div 2;
- XBase := (XMax - 472) div 2;
- YBase := (YMax div 2) - 64;
- InitUGraphics; { Reinitialize various graphics-item positions }
- end;
-
-
- {- Select Help when F1 pressed and a menu item is highlighted }
-
- procedure TMancalaWin.WMEnterIdle(var Msg: TMessage);
- begin
- if (Msg.WParam = msgf_Menu) and
- ((GetKeyState(vk_F1) and $8000) = $8000) then
- begin
- Help := true; { Causes help to be displayed rather than execute a command }
- PostMessage(HWindow, wm_KeyDown, vk_Return, 0); { Simulate Enter keypress }
- end;
- end;
-
-
- {- Tell help system to close its window if open }
-
- procedure TMancalaWin.WMDestroy(var Msg: TMessage);
- begin
- WinHelp(HWindow, HelpFileName, help_Quit, 0);
- TWindow.WMDestroy(Msg);
- end;
-
-
-
- end.
-
-
- { ----------------------------------------------------------------
- Copyright (c) 1991 by Swan Software. All rights reserved.
- Revision 1.00 Date: 8/21/1991
- ---------------------------------------------------------------- }
-